/*
 * Created by SharpDevelop.
 * User: Robert N. Tenney
 * Date: 3/22/2009
 * Time: 10:49 AM
 * 
 */
using System;
using System.Collections.Generic;
//using System.Reflection;
//using System.Diagnostics;
namespace Utility
{
    public static class TimeKeeper{
        private static Dictionary<string, TimeData> timeList;
        private static bool autoSave = true;
        private static string filename = "Timekeeper.log";
        
        static TimeKeeper(){
            timeList = new Dictionary<string, TimeData>();
        }
        
        public static bool AutoSave{
            get{
                return autoSave;
            }
            set {
                autoSave = value;
            }
        }
        
        public static string Filename{
            get{
                return filename;
            }
            set{
                filename = value;
            }
        }
        
        public static TimeData StartNew(){
            TimeData temp = new TimeData(getInfo());
            temp.Timer.Start();
            return temp;
        }
        
        public static void End(string title, TimeData timer){
            timer.Timer.Stop();
            timer.AddToTime();
            timer.CallCount++;
            if (timeList.ContainsKey(title)){
                timeList[title] = timer;
            } else{
                timeList.Add(title, timer);
            }
        }
        
        public static void End(TimeData timer){
            End(timer.Signature, timer);
        }
        
        public static void GenerateStatusList(){
            string format = "##.#######";
            foreach(KeyValuePair<string, TimeData> item in timeList){
                TimeData time = item.Value;
                MessagesHandler.Add(MessageTypes.DEBUG, time.ToString() +
                                    ", Called: " + time.CallCount + " time(s), Total time: " + time.Time.ToString(format) + " , Average time: " + time.AverageTime.ToString(format));
            }
        }

        
        private static Reflected getInfo(){
            Reflected temp = new Reflected();
            temp.ClassName = new System.Diagnostics.StackTrace().GetFrame(2).GetMethod().DeclaringType.Name;
            temp.MethodName = new System.Diagnostics.StackTrace().GetFrame(2).GetMethod().Name;
            temp.CalledBy = new System.Diagnostics.StackTrace().GetFrame(3).GetMethod().Name;
            if (temp.CalledBy == ".ctor") {
                temp.CalledBy = new System.Diagnostics.StackTrace().GetFrame(2).GetMethod().Name + ".CONSTRUCTOR";   
            }
            return temp;
        }
        
    }
    
    public struct Reflected{
        public string ClassName;
        public string MethodName;
        public string CalledBy;
    }
    /// <summary>
    /// Description of TimeData.
    /// </summary>
    public class TimeData
    {
        private string className;
        private string methodName;
        private string calledBy;
        private int callCount;
        private double time;
        private double shortestTime = Double.MaxValue;
        private double longestTime = 0.0;
        private Win32.HiPerfTimer timer;
        
        public TimeData(Reflected data)
        {
            this.className = data.ClassName;
            this.methodName = data.MethodName;
            this.calledBy = data.CalledBy;
            timer = new Win32.HiPerfTimer();
        }
        
        public Win32.HiPerfTimer Timer{
            get{
                return this.timer;
            }
            set{
                this.timer = value;
            }
        }
        
        public string ClassName{
            get{
                return this.className;
            }
        }
        
        public string MethodName{
            get{
                return this.methodName;
            }
        }
        
        public string CalledBy{
            get{
                return this.calledBy;
            }
        }
        
        public int CallCount{
            get{
                return this.callCount;
            }
            set{
                this.callCount = value;
            }
        }
        
        public double Time{
            get{
                return this.time;
            }
        }
        
        public double AverageTime{
            get{
                return this.time / (double)this.callCount;
            }
        }
        
        public void AddToTime(double value){
            this.time += value;
            if (shortestTime > value) {
                shortestTime = value;
            } else if (longestTime<value) {
                longestTime = value;
            }
        }
        
        public void AddToTime(){
            AddToTime(this.timer.Duration);
        }
        
        public string Signature{
            get{
                return this.ClassName + "." + this.MethodName + ", Called by: " + this.calledBy;
            }
        }
        
        public override string ToString()
        {
            return this.Signature;
        }
    }
}
